package com.mmall.util;

import com.mmall.pojo.User;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.codehaus.jackson.type.JavaType;
import org.codehaus.jackson.type.TypeReference;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by root on 18-4-30.
 */
@Slf4j
public class JasonUtil {

    private static ObjectMapper objectMapper = new ObjectMapper();

    {
        objectMapper.setSerializationInclusion(JsonSerialize.Inclusion.ALWAYS);
        objectMapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);
        objectMapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);
        objectMapper.setDateFormat(new SimpleDateFormat(DateTimeUtil.STANDARD_FORMAT));

        objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    public static <T> String  object2Str(T obj) {
        if (obj == null) {
            return null;
        }
        try {
           return obj instanceof String ? (String)obj : objectMapper.writeValueAsString(obj);
        } catch (IOException e) {
            log.warn("Parse object to string fail.", e);
            return null;
        }
    }

    public static <T> String  object2StrPretty(T obj) {
        if (obj == null) {
            return null;
        }
        try {
            return obj instanceof String ? (String)obj : objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
        } catch (IOException e) {
            log.warn("Parse object to string fail.", e);
            return null;
        }
    }

    public static <T> T str2Object(String str, Class<T> clazz) {
        if (StringUtils.isEmpty(str) || clazz == null) {
            return null;
        }
        try {
            return clazz.equals(String.class) ? (T)str : objectMapper.readValue(str, clazz);
        } catch (IOException e) {
            log.warn("Parse string to object fail.", e);
            return null;
        }

    }

    public static <T> T str2Object(String str, TypeReference<T> typeReference) {
        if (StringUtils.isEmpty(str) || typeReference == null) {
            return null;
        }
        try {
            return typeReference.getType().equals(String.class) ? (T)str : (T) objectMapper.readValue(str, typeReference);
        } catch (IOException e) {
           // log.warn("Parse string to object fail.", e);
            e.printStackTrace();
            return null;
        }
    }

    public static <T> T str2Object(String str, Class<?> collectionClass, Class<?>... elementClass) {
        JavaType javaType = objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClass);
        try {
            return objectMapper.readValue(str, javaType);
        } catch (IOException e) {
            log.warn("Parse string to object fail.", e);
            return null;
        }
    }


    public static void main(String[] args) {
       // testObj2Str();
        testStr2Obj();



    }

    private static void testObj2Str() {
        User user = new User();
        user.setUsername("yschan");
        user.setEmail("26573406@qq.com");
        String userStr = object2Str(user);

        System.out.println(userStr);


        List list = new ArrayList();
        list.add(user);
        list.add(user);
        String listStr = object2Str(list);
        RedisShardedPoolUtil.set("list", listStr);
        System.out.println(listStr);
    }

    private static void testStr2Obj() {
        String userStr = RedisShardedPoolUtil.get("user1");
        User user = str2Object(userStr, User.class);
        System.out.println(user.getUsername());
        System.out.println(user.getEmail());
        System.out.println(user.getId() == null);

        String listStr = RedisShardedPoolUtil.get("list");
        System.out.println(listStr);
        List<User> list = str2Object(listStr, new TypeReference<List<User>>(){});
        if (!CollectionUtils.isEmpty(list)) {
            for (User u : list) {
                System.out.println(u.getUsername());
            }
        }
    }


}
